﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Util;
using Spring.Data.NHibernate;
using uNhAddIns.SessionEasier;

namespace uNhAddIns.SpringAdapters.Tests
{
    public class ConversationSessionFactoryProvider : LocalSessionFactoryObject, ISessionFactoryProvider
    {
        private new static readonly ILog log = LogManager.GetLogger(typeof(ConversationSessionFactoryProvider));

        private IEnumerable<ISessionFactory> sessionFactories;
        private ISessionFactory sessionFactory;
        
        #region Implementation of IEnumerable
        public IEnumerator<ISessionFactory> GetEnumerator()
        {
            Initialize();
            return sessionFactories.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        #endregion

        #region Implementation of ISessionFactoryProvider
        public event EventHandler<EventArgs> BeforeCloseSessionFactory;
        public ISessionFactory GetFactory(string factoryId)
        {
            Initialize();
            return sessionFactory;
        }

        public void Initialize()
        {
            if (sessionFactory == null)
            {
                log.Debug("Initialize a new session factory reading the configuration.");
                sessionFactory = (ISessionFactory) GetObject();
                sessionFactories = new SingletonEnumerable<ISessionFactory>(sessionFactory);
            }
        }

        private void DoBeforeCloseSessionFactory()
        {
            if (BeforeCloseSessionFactory != null)
            {
                BeforeCloseSessionFactory(this, new EventArgs());
            }
        }
        #endregion

        #region IDisposable
        private bool disposed;

        public new void Dispose()
        {
            Dispose(true);
            base.Dispose();
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    if (sessionFactory != null)
                    {
                        DoBeforeCloseSessionFactory();
                        sessionFactory.Close();
                        sessionFactory = null;
                    }
                }
                disposed = true;
            }
        }
        #endregion

    }
}

/* TODO: Find out how the HibernateTemplate in Spring gets its ISessionFactory. 
 * How do DAOs get their ISessionFactory in uNhAddins examples?
*/